<template>
  <div class="notice-warp" :style="styles" v-if="isShow">
    <div class="notice-left">
      <template v-if="$slots.left"></template>
      <div v-else>通知</div>
    </div>
    <div class="notice-content-warp" ref="noticeContentWarp">
      <div
        class="notice-content"
        ref="noticeContent"
        :style="scrollableStyle"
        @transitionend="transitionEndEvent"
      >
        {{ content }}
      </div>
    </div>
    <div class="notice-right" v-if="closeable" @click="closeEvent">关闭</div>
  </div>
</template>
<script>
import { raf, doubleRaf } from "@/utils/raf";

export default {
  name: "notice",
  props: {
    // 显示 :show.sync
    show: {
      type: Boolean,
      default: true,
    },
    //   滚动内容
    content: {
      type: String,
      default: "",
    },
    // 背景颜色
    color: String,
    // 背景颜色
    background: String,
    // 是否开启滚动
    scrollable: {
      type: Boolean,
      default: true,
    },
    // 是否多行显示
    wrapable: {
      type: Boolean,
      default: false,
    },
    // 动画延迟时间 (s)
    delay: {
      type: Number,
      default: 1,
    },
    // 滚动速率 (px/s)
    speed: {
      type: Number,
      default: 60,
    },
    // 可关闭
    closeable: {
      type: Boolean,
      default: false,
    },
  },
  watch: {
    content: {
      handler(val) {
        // 计算内容宽度
        let startTimer = null;
        const ms = this.isDef(this.delay) ? +this.delay * 1000 : 0;
        startTimer && clearTimeout(startTimer);
        startTimer = setTimeout(() => {
          // 如果没有内容 或者不开启滚动就关闭定时器
          if (!val || this.scrollable === false || this.wrapable === true) {
            startTimer && clearTimeout(startTimer);
            return;
          }
          this.reset();
          // 获取父容器宽度、容器宽度
          this.wrapRefWidth =
            this.$refs.noticeContentWarp.getBoundingClientRect().width;
          this.contentRefWidth =
            this.$refs.noticeContent.getBoundingClientRect().width;
          if (this.scrollable || this.contentRefWidth > this.wrapRefWidth) {
            doubleRaf(() => {
              this.offset = -this.contentRefWidth;
              this.duration = this.contentRefWidth / +this.speed;
            });
          }
        }, ms);
      },
      immediate: true,
      deep: true,
    },
  },
  computed: {
    styles() {
      let styles = {};
      if (this.color) {
        styles.color = this.color;
      }
      if (this.background) {
        styles.background = this.background;
      }
      const ellipsis = this.scrollable === false && this.wrapable;
      if (ellipsis) {
        styles.height = "auto";
        styles.padding = "8px 16px";
      }
      return Object.keys(styles).length == 0 ? "" : styles;
    },
    scrollableStyle() {
      const style = {
        transform: this.offset ? `translateX(${this.offset}px)` : "",
        transitionDuration: `${this.duration}s`,
      };
      return style;
    },
    isShow: {
      get() {
        return this.show;
      },
      set(val) {
        this.$emit("update:show", val);
      },
    },
  },
  data() {
    return {
      wrapRefWidth: 0,
      contentRefWidth: 0,
      offset: 0,
      duration: 0,
    };
  },
  methods: {
    isDef(val) {
      return val !== undefined && val !== null;
    },
    reset() {
      this.offset = 0;
      this.duration = 0;
      this.wrapRefWidth = 0;
      this.contentRefWidth = 0;
    },
    // 动画过渡完成事件
    transitionEndEvent() {
      this.offset = this.wrapRefWidth;
      this.duration = 0;
      raf(() => {
        doubleRaf(() => {
          this.offset = -this.contentRefWidth;
          this.duration =
            (this.contentRefWidth + this.wrapRefWidth) / this.speed;
        });
      });
    },
    // 关闭事件
    closeEvent() {
      this.isShow = false;
      this.$emit("closeEvent");
    },
    test() {
      //    <notice
      //         :content="content"
      //         :show.sync="show"
      //         :closeable="true"
      //         @closeEvent="closeEvent"
      //       />
    },
  },
};
</script>
<style lang="scss" scoped>
.notice-warp {
  position: relative;
  display: -webkit-box;
  display: -webkit-flex;
  display: flex;
  -webkit-box-align: center;
  -webkit-align-items: center;
  align-items: center;
  height: 40px;
  padding: 0 16px;
  color: #ed6a0c;
  font-size: 14px;
  line-height: 24px;
  background-color: #fffbe8;
  .notice-left,
  .notice-right {
    min-width: 40px;
  }
  .notice-right {
    text-align: right;
  }
  .notice-content-warp {
    position: relative;
    display: -webkit-box;
    display: -webkit-flex;
    display: flex;
    -webkit-box-flex: 1;
    -webkit-flex: 1;
    flex: 1;
    -webkit-box-align: center;
    -webkit-align-items: center;
    align-items: center;
    height: 100%;
    overflow: hidden;
    .notice-content {
      position: absolute;
      white-space: nowrap;
      -webkit-transition-timing-function: linear;
      transition-timing-function: linear;
    }
  }
}
</style>
